package com.sugon.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.sugon.dao.DevMainBaseDao;
import com.sugon.dao.DevMaintenPlanDao;
import com.sugon.dao.SysUserRoleDao;
import com.sugon.entity.*;
import com.sugon.entity.dto.DevMaintenanceDirectiveRulesItemDTO;
import com.sugon.entity.dto.MaintenanceRuleImportParam;
import com.sugon.modules.base.model.vo.ProcessProgressConst;
import com.sugon.modules.utils.DateUtil;
import com.sugon.service.*;
import com.sugon.utils.*;
import org.apache.shiro.util.Assert;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 维护规程管理Service实现类
 *
 * @author sugon
 * @date 2019-07-17 15:38:48
 */
@Service("devMaintenPlanService")
public class DevMaintenPlanServiceImpl implements DevMaintenPlanService {

    @Autowired
    private DevMaintenPlanDao devMaintenPlanDao;
    @Autowired
    private SysMsgService sysMsgService;
    @Autowired
    private SysUserRoleDao sysUserRoleDao;
    @Autowired
    private SysDeptService deptService;
    @Resource
    private DeviceInfoService deviceService;
    @Resource
    private DevMainBaseDao devMainBaseDao;
    @Resource
    private DevPmRuleItemService devPlanOptionService;

    /**
     * 生成规程版本
     *
     * @param data
     * @return
     */
    @Override
    public String generateUniqueCode(Object data) {
        DevMaintenPlanEntity devPmRule = (DevMaintenPlanEntity) data;
        String workshop = ShiroUtils.getWorkshop();
        Assert.notNull(workshop, "只有处于某部门下的用户执行该操作！");
        // 设置备件需求计划编码
        SysDeptEntity deptEntity = deptService.queryObject(workshop);
        Assert.notNull(deptEntity, "非法所属部门编码！");
        String planVersionPrefix = deptEntity.getDcode() + "-" + DateUtil.getYearAndMonth(null) + "-";
        String lastDCode = devMaintenPlanDao.getLastDCode(devPmRule.getDevId(), planVersionPrefix);
        return com.sugon.modules.utils.StrUtil.increase(lastDCode, planVersionPrefix, 2, 1);
    }

    /**
     * @param id 主键
     * @return
     */
    @Override
    public DevMaintenPlanEntity queryObject(String id) {
        return devMaintenPlanDao.queryObject(id);
    }

    /**
     * @param devCode     设备编码
     * @param planVersion 规程版本
     * @return
     */
    @Override
    public boolean checkExists(String devCode, String planVersion) {
        Map<String, Object> param = new HashMap<>(2);
        param.put("devCode", devCode);
        param.put("planVersion", planVersion);
        return queryTotal(param) > 0;
    }

    @Override
    public List<DevMaintenPlanEntity> list(String devId, Integer progress, Integer isValid) {
        Map<String, Object> param = MapUtil.newHashMap();
        param.put("devId", devId);
        if (progress != null) {
            param.put("progress", progress);
        }
        if (isValid != null) {
            param.put("isValid", isValid);
        }
        return queryList(param);
    }

    /**
     * @param map 参数
     * @return
     */
    @Override
    public List<DevMaintenPlanEntity> queryList(Map<String, Object> map) {
        List<String> list = sysUserRoleDao.queryRoleIdList(ShiroUtils.getUserId());
        for (int i = 0; i < list.size(); i++) {
            String code = list.get(i);
            if (code.equals(Constant.ZZC_PESQ)) {//pe授权工程师
                map.put("checkStatus", 1);
            }
        }
        return devMaintenPlanDao.queryList(map);
    }

    /**
     * @param map 参数
     * @return
     */
    @Override
    public int queryTotal(Map<String, Object> map) {
        List<String> list = sysUserRoleDao.queryRoleIdList(ShiroUtils.getUserId());
        for (int i = 0; i < list.size(); i++) {
            if (Constant.ZZC_PESQ.equals(list.get(i))) {//pe授权工程师
                map.put("checkStatus", 1);
            }
        }
        return devMaintenPlanDao.queryTotal(map);
    }

    /**
     * @param devMaintenPlan 实体
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int save(DevMaintenPlanEntity devMaintenPlan) {
        SysUserEntity sysUserEntity = ShiroUtils.getUserEntity();
        devMaintenPlan.setId(RandomUtil.randomString(32));
        devMaintenPlan.setDelFlag(Constant.IS_NOT_DEL_INT);
        devMaintenPlan.setOrgUserId(sysUserEntity.getUserId());
        devMaintenPlan.setOrgUserName(sysUserEntity.getNickName());
        devMaintenPlan.setPlanVersion(generateUniqueCode(devMaintenPlan));
        // 保存规程项信息
        return devMaintenPlanDao.save(devMaintenPlan);
    }

    /**
     * @param devMaintenPlan 实体
     * @return
     */
    @Override
    public int update(DevMaintenPlanEntity devMaintenPlan) {
        int rows = devMaintenPlanDao.update(devMaintenPlan);
        if (rows > 0) {
            SysMsgEntity msgEntity = new SysMsgEntity();
            String Id = devMaintenPlan.getId();
            msgEntity.setDataId(Id);
            msgEntity.setDataUrl("../device/devmaintenplan.html?Id=" + Id);
            sysMsgService.addApproveItem(ProcessInfoEnum.DEV_WHGC, msgEntity, 0);
        }
        return rows;
    }

    @Override
    public Map<String, Object> prepareExportData(Map<String, Object> params) {
        // 只查看最新，处于有效状态的设备维护规程
        params.put("isValid", 1);
        List<DevMaintenanceDirectiveRulesItemDTO> devPmRuleList = devMaintenPlanDao.queryItemList(params);
        if (devPmRuleList == null) {
            devPmRuleList = CollectionUtil.newArrayList();
        }
        // 构建返回数据
        Map<String, Object> resultMap = MapUtil.newHashMap();
        resultMap.put("list", devPmRuleList);
        return resultMap;
    }

    /**
     * @param id
     * @return
     */
    @Override
    public int delete(String id) {
        return devMaintenPlanDao.delete(id);
    }

    /**
     * @param ids
     * @return
     */
    @Override
    public int deleteBatch(String[] ids) {
        return devMaintenPlanDao.deleteBatch(ids);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String imports2(MultipartFile file) {
        String importResult = "生成新设备维护规程数：{}，维护项条数：{}。<br /> {}台设备的维护内容未发生变化，不做任何处理！";
        // 上传Excel内容不得为空
        if (file == null || file.isEmpty()) {
            throw new RRException("上传文件不能为空");
        }
        // 导入规程数
        int rows = 0;
        List<String> unChangedList = CollectionUtil.newArrayList();
        // 导入维护项条数
        int itemRows = 0;
        ImportParams importParams = new ImportParams();
        importParams.setNeedVerify(true);
        // 需要读取所有sheet
        importParams.setSheetNum(0);
        List<MaintenanceRuleImportParam> ruleParams = null;
        try {
            // 读取内容
            ruleParams = ExcelImportUtil.importExcel(file.getInputStream(), MaintenanceRuleImportParam.class, importParams);
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 如果无法读取内容，则直接返回
        if (CollectionUtil.isEmpty(ruleParams)) {
            return StrUtil.format(importResult, rows, itemRows);
        }
        // 按照设备进行分组
        Map<String, List<MaintenanceRuleImportParam>> devRuleMap = ruleParams.stream().collect(Collectors.groupingBy(MaintenanceRuleImportParam::getDevCode));
        Set<Map.Entry<String, List<MaintenanceRuleImportParam>>> entrySet = devRuleMap.entrySet();
        String devCode;
        List<MaintenanceRuleImportParam> maintenanceItemList;
        outer:
        for (Map.Entry<String, List<MaintenanceRuleImportParam>> entry : entrySet) {
            devCode = StrUtil.trim(entry.getKey());
            // 查找设备是否存在，如果不存在，则直接跳过
            DeviceInfoEntity device = deviceService.getInfoByDevCode(devCode);
            if (device == null) {
                continue;
            }
            // 保存规程项
            maintenanceItemList = entry.getValue();
            // 去除重复元素：防止客户在拍计划时同一个维护项排了多次
            maintenanceItemList = maintenanceItemList.stream().filter(DeduplicationUtil.distinctByKey(MaintenanceRuleImportParam::getCode)).collect(Collectors.toList());
            // 获取设备维护项列表。如果不存在，则跳过
            List<DevMainBaseEntity> devPmItemList = devMainBaseDao.listByCodeList(maintenanceItemList.stream().map(MaintenanceRuleImportParam::getCode).collect(Collectors.toList()));
            if (CollectionUtil.isEmpty(devPmItemList)) {
                continue;
            }
            // 设置基础信息
            DevMaintenPlanEntity devMaintenPlan = new DevMaintenPlanEntity();
            devMaintenPlan.setReserve1("2");
            devMaintenPlan.setRuleName(device.getDevName() + "_维护规程");
            devMaintenPlan.setDevId(device.getId());
            devMaintenPlan.setIsValid(1);
            devMaintenPlan.setPlanCon("无");
            devMaintenPlan.setProgress(ProcessProgressConst.DEPT_APPROVING);

            // 校验校验设备的新老规程 维护项是否发生变化。如果未发生变化，那么不做任何处理
            List<DevMaintenPlanEntity> existedPmRuleList = list(device.getId(), ProcessProgressConst.PASSED, 1);
            if (CollectionUtil.isNotEmpty(existedPmRuleList)) {
                // 理论上一个设备 只有一个处于使用中的维护规程
                DevMaintenPlanEntity existedPmRule = existedPmRuleList.get(0);
                // 获取目前在用的设备维护规程项
                List<DevPlanOptionEntity> oldDevRuleOptionList = devPlanOptionService.getByPlanId(existedPmRule.getId());
                cn.hutool.core.lang.Assert.notEmpty(oldDevRuleOptionList);
                /*
                    校验新老规程是否发生变化。如果未发生变化，则不会生成新的设备维护规程
                 */
                if (CollectionUtil.isEqualList(devPmItemList.stream().map(DevMainBaseEntity::getId).sorted(String::compareTo).collect(Collectors.toList()), oldDevRuleOptionList.stream().map(DevPlanOptionEntity::getMainBaseId).sorted(String::compareTo).collect(Collectors.toList()))) {
                    unChangedList.add(devCode);
                    continue;
                }
                // 设置老规程ID
                devMaintenPlan.setPreRuleId(existedPmRule.getId());
            }
            rows += save(devMaintenPlan);
            if (rows > 0) {
                for (DevMainBaseEntity devPmItem : devPmItemList) {
                    //维护规程与维护库关联
                    DevPlanOptionEntity devPlanOption = new DevPlanOptionEntity(devMaintenPlan.getId(), devPmItem.getId());
                    itemRows += devPlanOptionService.save(devPlanOption);
                }
            }
        }
        return StrUtil.format(importResult, rows, itemRows, unChangedList.size());
    }

}
